﻿package 
{

	import com.bit101.components.*;
	
	import fl.controls.*;
	import fl.data.DataProvider;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.NetStatusEvent;
	import flash.events.StatusEvent;
	import flash.events.SyncEvent;
	import flash.events.TimerEvent;
	import flash.media.Camera;
	import flash.media.H264Level;
	import flash.media.H264Profile;
	import flash.media.H264VideoStreamSettings;
	import flash.media.ID3Info;
	import flash.media.Microphone;
	import flash.media.MicrophoneEnhancedMode;
	import flash.media.MicrophoneEnhancedOptions;
	import flash.media.SoundCodec;
	import flash.media.Video;
	import flash.net.*;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.text.StaticText;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.ui.Mouse;
	import flash.utils.Timer;
	
	import flashx.textLayout.elements.BreakElement;
	
	import red5.*;

	public class Main extends Sprite
	{

		public var nc:NetConnection;
		public var input_host:fl.controls.TextInput;
		public var input_chat:fl.controls.TextInput;
		public var status_a:fl.controls.Label;
		public var total_ol:fl.controls.Label;
		public var room_info:fl.controls.Label;
		public var btn_connect:fl.controls.Button;
		public var aCb:fl.controls.ComboBox;
		public var button:fl.controls.Button;
		
		//public var result:fl.controls.TextArea;
		public var ta_chat:fl.controls.TextArea;
		// Video  var
		
		private var video_publish:Video;
		private var video_voteback:Video;
		private var ns_voteback:NetStream;
		private var ns_publish:NetStream;
		private var cam:Camera;
		private var mic:Microphone;
		private var h264Settings:H264VideoStreamSettings;
		private var options:MicrophoneEnhancedOptions
		//SharedObject
		public var so_ol:SharedObject;

		//public var ol:TextArea;
		
		public var grid_online:DataGrid;
		public var textformat1: TextFormat;
		//info
		public var room_id:String;
		public var name_client:String;
		public var address_client:String;
		public var type_client:String;
		public var masv:String;
		public var lastmasv:String;

		//list
		


		public function Main()
		{
			init();
			//connect();

		}
		private function init():void
		{
			//INIT
			h264Settings = new H264VideoStreamSettings();
			h264Settings.setProfileLevel(H264Profile.MAIN, H264Level.LEVEL_3_1);
			options = new MicrophoneEnhancedOptions();
			options.mode = MicrophoneEnhancedMode.FULL_DUPLEX;
			options.echoPath = 128;
			options.nonLinearProcessing = true;
			lastmasv = "null";
			
			this.input_host = fl.controls.TextInput(this.getChildByName("link"));
			this.input_chat = fl.controls.TextInput(this.getChildByName("input_chat"));
			
			this.status_a = fl.controls.Label(this.getChildByName("lbl_status"));
			this.total_ol = fl.controls.Label(this.getChildByName("lbl_total"));
			this.room_info = fl.controls.Label(this.getChildByName("lbl_room_info"));
			this.btn_connect = fl.controls.Button(this.getChildByName("btn_connect"));
			

			//this.result=fl.controls.TextArea(this.getChildByName("ta_result"));
			this.ta_chat = fl.controls.TextArea(this.getChildByName("ta_chat"));
			//EVENT
			this.input_chat.addEventListener(KeyboardEvent.KEY_DOWN,input_chat_enter);
			this.root.loaderInfo.addEventListener(Event.COMPLETE,loaderComplete);
			this.btn_connect.addEventListener(MouseEvent.CLICK,btn_connect_click);
			
			
			button = new fl.controls.Button();
			addChild(button);
			button.x = 600;
			button.y = 560;
			button.width = 150;
			button.label = "Click to change";
			button.addEventListener(MouseEvent.CLICK,changeCamera);
			
			aCb = new fl.controls.ComboBox();
			aCb.dropdownWidth = 210;
			aCb.width = 200;
			aCb.move(600, 540);
			aCb.prompt = "Choice Camera will change";
			aCb.dataProvider = new DataProvider(Camera.names);
			addChild(aCb);
			
			//REMOTECLASS;

			registerClassAlias("org.red5.core.Client",Client);

			//NET CONNECTION
			nc = new NetConnection();
			nc.client = { onBWDone: function():void{ trace("onBWDone") } };
			nc.addEventListener(NetStatusEvent
			.NET_STATUS , netStatus);

			

			cam = Camera.getCamera();
			//cam.addEventListener(StatusEvent.STATUS,handleCameraStatus,false,0,true);
			cam.setMode(640, 480, 25);
			cam.setQuality(0,90);

			mic = Microphone.getEnhancedMicrophone();
			//mic.addEventListener(StatusEvent.STATUS,handleMicrophoneStatus,false,0,true);
//			mic.enableVAD = true;
//			mic.encodeQuality = 10;
//			mic.rate = 44;
//			mic.setLoopBack(false);
//			mic.setUseEchoSuppression(true);
			
			mic.codec = SoundCodec.SPEEX;
			mic.framesPerPacket = 1;
			mic.setSilenceLevel(0, 2000);
			mic.gain = 50;
			mic.setLoopBack(false);
			mic.enhancedOptions = options;
			
			
			video_voteback = new Video(5,5);
			video_voteback.x = 15;
			video_voteback.y = 5;
			

			video_publish = new Video(640,480);
			video_publish.x = 15;
			video_publish.y = 5;

			//video_publish.attachNetStream((new NetStream(nc)).appendBytesAction("screen://0,0,160,120/10"));
			addChild(video_publish);
			
			
			//Datagrid OnlineList
			this.grid_online=DataGrid(this.getChildByName("grid_online"));
			this.grid_online.showHeaders=false;
			this.grid_online.columns=["name","address","Action2"];
			this.grid_online.columns[0].width=100;
			this.grid_online.columns[1].width=180;
			
			Bell.main=this;
			this.grid_online.columns[2].cellRenderer = Bell;
			
			this.grid_online.rowHeight=28;

			
			this.textformat1=new TextFormat();
			this.textformat1.size=11;
			
			
			//this.mygrid.setStyle("textFormat",this.textformat2);
			this.grid_online.setRendererStyle("textFormat",this.textformat1);
			
			//this.grid_online.dataProvider=new DataProvider(arr_data);
		}
		public function loaderComplete(e:Event):void
		{
			//get FlashVars Here
			var paras:Object = this.root.loaderInfo.parameters;
			var key:String;
			var value:String;

			for (key in paras)
			{
				value = String(paras[key]);


			}
			if (paras["room_id"] != null)
			{
				this.room_id = paras["room_id"];
			}
			else
			{
				this.room_id = "1";

			}
			this.room_info.text +=  "\nPhòng: room_" + this.room_id + "\n";
			this.input_host.text = "rtmp://118.69.55.61/firstapp/room" + room_id;

			if (paras["address"] != null)
			{
				this.address_client = paras["address"];
			}
			else
			{
				this.address_client = "Address 1";

			}
			if (paras["name"] != null)
			{
				this.name_client = paras["name"];
			}
			else
			{
				this.name_client = "Dam Hai";

			}
		//	if(paras["masv"]!=null)this.masv=paras["masv"];
		   this.masv=randomRange(5000,2).toString(4);
			trace(this.masv);
			type_client = "gv";
			connect();
		}//end loadcomplete
		private function connect()
		{
			var link:String = this.input_host.text;
			nc.connect(link,this.name_client,this.masv,this.type_client);

			var so_name:String = "OnlineList";
			this.so_ol = SharedObject.getRemote(so_name,nc.uri,false);
			this.so_ol.client = this;
			this.so_ol.addEventListener(SyncEvent.SYNC,on_so_ol_sync);
			this.so_ol.connect(nc);

			var room:String = "room" + this.room_id;
			var responder:Responder = new Responder(on_getOldMessage_Complete,on_getOldMessage_fail);
			this.nc.call("getOldMessage",responder,room);
		}
		private function changeCamera(ev:MouseEvent):void
		{
			if (ns_publish != null)
			{
				if (ns_publish.info.isLive == true)
				{
					ns_publish.close();
					ns_publish = null;
				}
			}
			cam = Camera.getCamera(aCb.selectedIndex.toString());
			cam.setMode(800, 600, 25);
			cam.setQuality(0,90);
			if(nc.connected == true)
			{
				publishVideo();
			}
			video_publish.attachCamera(cam);
		}
		private function btn_connect_click(event:MouseEvent):void
		{
			var tempt:Button = Button(event.currentTarget);
			if (tempt.label == "Connect")
			{
				var link:String = this.input_host.text;
				nc.connect(link,this.name_client);

				//this.status_a.text+=" "+tensv;
				tempt.label = "Disconnect";


				var so_name:String = "OnlineList";
				this.so_ol = SharedObject.getRemote(so_name,nc.uri,false);
				this.so_ol.client = this;
				this.so_ol.addEventListener(SyncEvent.SYNC,on_so_ol_sync);
				this.so_ol.connect(nc);

				var room:String = "room" + this.room_id;
				var responder:Responder = new Responder(on_getOldMessage_Complete,on_getOldMessage_fail);
				this.nc.call("getOldMessage",responder,room);

			}
			else
			{
				nc.close();

				tempt.label = "Connect";

			}
		}
		private function input_chat_enter(event:KeyboardEvent):void
		{
			if(event.charCode == 13){
				
				// your code here
			
			
			//var room_name:String="room"+this.room_id;		
				var scope:String="room"+this.room_id;
				var message:String=this.name_client+": "+this.input_chat.text;
				if(message!=""&&this.nc.connected==true)
				{
					var responder:Responder = new Responder(on_btn_connect_Complete, on_btn_connect_fail);
					this.nc.call("sendMessage",null,scope,message);	
				}
				this.input_chat.text="";
			}
		}//end input_chat_enter

		private function publishVideo():void
		{
			ns_publish = new NetStream(nc);
			ns_publish.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
			ns_publish.attachCamera(cam);
			ns_publish.attachAudio(mic);
			ns_publish.videoStreamSettings = h264Settings;
			ns_publish.publish(room_id, "live");
			//ns_publish.publish("test1.flv", "live");

			trace();
		}

		private function on_btn_connect_Complete(result:Object):void
		{
			this.ta_chat.appendText(result.toString());
		}
		private function on_btn_connect_fail(result:Object):void
		{
			this.ta_chat.appendText(result.toString());
		}
		//get old message chat in room;
		private function on_getOldMessage_Complete(result:Object):void
		{
			if (result.toString() != "")
			{
				this.ta_chat.text = result.toString();
				this.ta_chat.verticalScrollPosition=this.ta_chat.maxVerticalScrollPosition;

			}
		}
		function randomRange(max:Number, min:Number = 0):Number
		{
			return Math.random() * (max - min) + min;
		}
		private function on_getOldMessage_fail(result:Object):void
		{
			this.ta_chat.appendText(result.toString());
		}

		public function receiveMessage(mesg:String):void
		{
			this.ta_chat.appendText(mesg+"\n");
			this.ta_chat.verticalScrollPosition=this.ta_chat.maxVerticalScrollPosition;
		}


		private function on_so_ol_sync(event:SyncEvent):void
		{
			if (event.changeList[0].code == "clear")
			{
				switch (event.changeList[1].code)
				{
					case "success" :
						update_online_list(event.target.data);
						break;
					case "change" :
						update_online_list(event.target.data);
						break;
				}
			}
			else
			{
				switch (event.changeList[1].code)
				{
					case "success" :
						update_online_list(event.target.data);
						break;
					case "change" :
						update_online_list(event.target.data);
						break;
				}
			}

		}


		private function update_online_list(data:Object):void
		{
			this.room_info.text ="Chưa có giảng viên tham gia";
			if(data["count"]!=null)
			{
				this.total_ol.text=data["count"];
				var list_SV:Array=new Array();
				list_SV=data["ol"] as Array;
				var arr_data:Array=new Array();
				
				for(var i:String in list_SV)
				{
					var obj:Object = new Object();
					var client:Client=list_SV[i] as Client;
					//define properties to the objects
					obj.id =client.client_id ;
					obj.masv = client.getclient_cer();
					obj.name = client.name;
					obj.address=client.address;
					obj.bell_status=client.vote_status;
					if(client.getclient_type()=="gv"){
						this.room_info.text = "Thông tin giảng viên: " + client.getname(); 
					}else{
						arr_data.push(obj);
					}
				}
				
				
				//define properties to the objects
				
				trace(arr_data);
				this.grid_online.dataProvider=new DataProvider(arr_data);
				this.grid_online.showHeaders=false;
			}


		}//end update_online_list
		private function netStatus(event:NetStatusEvent):void
		{
			switch (event.info.code)
			{
				case "NetConnection.Connect.Rejected" :

					this.status_a.text = "Rejected";
					break;
				case "NetConnection.Connect.Success" :
					//playbackVideo();
					publishVideo();
					video_publish.attachCamera(cam);
					//video_publish.attachNetStream(ns_publish);
					this.status_a.text = this.name + " Connected ";
					break;
				case "NetConnection.Connect.Closed" :

					this.status_a.text = "Closed";
					//this.result.text="";
					
					this.ta_chat.text = "";
					this.total_ol.text = "";
					break;
				case "NetConnection.Call.Failed" :

					this.status_a.text = "Call Fail";
					break;

			}//end switch
		}//end netstatus
		private function handleStreamStatus(e:NetStatusEvent):void
		{
			switch (e.info.code)
			{
				case 'NetStream.Buffer.Empty' :
					trace("Video Netstream Buffer Empty");
					break;
				case 'NetStream.Buffer.Full' :
					trace("Video Netstream Buffer Full");
					break;
				case 'NetStream.Buffer.Flush' :
					trace("Video Netstream Buffer Flushed!!!!");
					break;
			}
		}
		private function on_btn_vote_Complete(result:Object):void
		{
			trace("Accept Complete");
		}
		private function on_btn_vote_fail(result:Object):void
		{
			trace("Accept False");
		}
		//edit by dung 12/07
		public function demofunction(currenMasv:String):void
		{
			trace("last massv"+ lastmasv);
			if(lastmasv!="null")
			{
				closeStreamClient(lastmasv);
			}
			var scope:String="room"+this.room_id;
			var message:String="accept";
			if(message!=""&&this.nc.connected==true)
			{
				var responder:Responder = new Responder(on_btn_vote_Complete, on_btn_vote_fail);
				this.nc.call("sendCommand",responder,scope,message, currenMasv);	
			}
			
			trace("Accept Client vote");
			lastmasv = currenMasv;
		}
		public function closeStreamClient(currenMasv:String):void
		{
			var scope:String="room"+this.room_id;
			var message:String="reject";
			if(message!=""&&this.nc.connected==true)
			{
				var responder:Responder = new Responder(on_btn_vote_Complete, on_btn_vote_fail);
				this.nc.call("sendCommand",responder,scope,message, currenMasv);	
			}
			
			trace("Close all stream");
		}
		public function receiveCommand(mesg:String):void
		{
			// This blank will fill by some code to occour some thing.
			trace(mesg);
			var comArray:Array = mesg.split("-");
			trace("Commmad: " + comArray[0]);
			trace("Client cer:" + comArray[1]);
			var clientCer:String = comArray[1];
			var command:String = comArray[0];
			if(command == "accept")
			{
				
				ns_voteback = new NetStream(nc);
				ns_voteback.addEventListener(NetStatusEvent.NET_STATUS, handleStreamStatus);
				ns_voteback.inBufferSeek = true;
				video_voteback.attachNetStream(ns_voteback);
				ns_voteback.play(clientCer, -1);
				trace("Client has been Subscribe stream: " + masv);
				
			}if(command =="reject")
			{
				ns_voteback.close();
				trace("All client has been remove stream");
			}			
		}

	}

}